Imports System.Math
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Graphics

Public Class FlexMapViewerC
    Inherits System.Windows.Forms.UserControl

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents pnlBorder As System.Windows.Forms.Panel
    Friend WithEvents txtX As System.Windows.Forms.TextBox
    Friend WithEvents txtY As System.Windows.Forms.TextBox
    Friend WithEvents txtZoom As System.Windows.Forms.TextBox
    Friend WithEvents lblCoordinates As System.Windows.Forms.Label
    Friend WithEvents lblZoom As System.Windows.Forms.Label
    Friend WithEvents picDisplay As System.Windows.Forms.PictureBox
    Friend WithEvents picTempBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picSmallBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picBridge As System.Windows.Forms.PictureBox
    Friend WithEvents picHeavyBridge As System.Windows.Forms.PictureBox
    Friend WithEvents tmrGeneral As System.Windows.Forms.Timer
    Friend WithEvents picBlankImage As System.Windows.Forms.PictureBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(FlexMapViewerC))
        Me.pnlBorder = New System.Windows.Forms.Panel
        Me.picDisplay = New System.Windows.Forms.PictureBox
        Me.txtX = New System.Windows.Forms.TextBox
        Me.txtY = New System.Windows.Forms.TextBox
        Me.txtZoom = New System.Windows.Forms.TextBox
        Me.lblCoordinates = New System.Windows.Forms.Label
        Me.lblZoom = New System.Windows.Forms.Label
        Me.picTempBridge = New System.Windows.Forms.PictureBox
        Me.picSmallBridge = New System.Windows.Forms.PictureBox
        Me.picBridge = New System.Windows.Forms.PictureBox
        Me.picHeavyBridge = New System.Windows.Forms.PictureBox
        Me.tmrGeneral = New System.Windows.Forms.Timer(Me.components)
        Me.picBlankImage = New System.Windows.Forms.PictureBox
        Me.pnlBorder.SuspendLayout()
        Me.SuspendLayout()
        '
        'pnlBorder
        '
        Me.pnlBorder.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.pnlBorder.BackColor = System.Drawing.Color.Black
        Me.pnlBorder.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.pnlBorder.Controls.Add(Me.picBlankImage)
        Me.pnlBorder.Controls.Add(Me.picDisplay)
        Me.pnlBorder.Location = New System.Drawing.Point(0, 0)
        Me.pnlBorder.Name = "pnlBorder"
        Me.pnlBorder.Size = New System.Drawing.Size(464, 384)
        Me.pnlBorder.TabIndex = 3
        Me.pnlBorder.TabStop = True
        '
        'picDisplay
        '
        Me.picDisplay.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.picDisplay.BackColor = System.Drawing.Color.Black
        Me.picDisplay.Location = New System.Drawing.Point(2, 2)
        Me.picDisplay.Name = "picDisplay"
        Me.picDisplay.Size = New System.Drawing.Size(458, 378)
        Me.picDisplay.TabIndex = 0
        Me.picDisplay.TabStop = False
        '
        'txtX
        '
        Me.txtX.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.txtX.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtX.Location = New System.Drawing.Point(0, 360)
        Me.txtX.Name = "txtX"
        Me.txtX.ReadOnly = True
        Me.txtX.Size = New System.Drawing.Size(72, 20)
        Me.txtX.TabIndex = 0
        Me.txtX.Text = "0"
        Me.txtX.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtX.Visible = False
        '
        'txtY
        '
        Me.txtY.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.txtY.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtY.Location = New System.Drawing.Point(71, 360)
        Me.txtY.Name = "txtY"
        Me.txtY.ReadOnly = True
        Me.txtY.Size = New System.Drawing.Size(72, 20)
        Me.txtY.TabIndex = 1
        Me.txtY.Text = "0"
        Me.txtY.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtY.Visible = False
        '
        'txtZoom
        '
        Me.txtZoom.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.txtZoom.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.txtZoom.Location = New System.Drawing.Point(384, 360)
        Me.txtZoom.Name = "txtZoom"
        Me.txtZoom.Size = New System.Drawing.Size(72, 20)
        Me.txtZoom.TabIndex = 2
        Me.txtZoom.Text = "100"
        Me.txtZoom.TextAlign = System.Windows.Forms.HorizontalAlignment.Center
        Me.txtZoom.Visible = False
        '
        'lblCoordinates
        '
        Me.lblCoordinates.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.lblCoordinates.Location = New System.Drawing.Point(152, 363)
        Me.lblCoordinates.Name = "lblCoordinates"
        Me.lblCoordinates.Size = New System.Drawing.Size(72, 16)
        Me.lblCoordinates.TabIndex = 4
        Me.lblCoordinates.Text = "Coordinates"
        Me.lblCoordinates.Visible = False
        '
        'lblZoom
        '
        Me.lblZoom.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.lblZoom.Location = New System.Drawing.Point(336, 363)
        Me.lblZoom.Name = "lblZoom"
        Me.lblZoom.Size = New System.Drawing.Size(40, 16)
        Me.lblZoom.TabIndex = 5
        Me.lblZoom.Text = "Zoom"
        Me.lblZoom.TextAlign = System.Drawing.ContentAlignment.MiddleRight
        Me.lblZoom.Visible = False
        '
        'picTempBridge
        '
        Me.picTempBridge.Image = CType(resources.GetObject("picTempBridge.Image"), System.Drawing.Image)
        Me.picTempBridge.Location = New System.Drawing.Point(240, 328)
        Me.picTempBridge.Name = "picTempBridge"
        Me.picTempBridge.Size = New System.Drawing.Size(16, 16)
        Me.picTempBridge.TabIndex = 6
        Me.picTempBridge.TabStop = False
        '
        'picSmallBridge
        '
        Me.picSmallBridge.Image = CType(resources.GetObject("picSmallBridge.Image"), System.Drawing.Image)
        Me.picSmallBridge.Location = New System.Drawing.Point(264, 328)
        Me.picSmallBridge.Name = "picSmallBridge"
        Me.picSmallBridge.Size = New System.Drawing.Size(16, 16)
        Me.picSmallBridge.TabIndex = 7
        Me.picSmallBridge.TabStop = False
        '
        'picBridge
        '
        Me.picBridge.Image = CType(resources.GetObject("picBridge.Image"), System.Drawing.Image)
        Me.picBridge.Location = New System.Drawing.Point(288, 328)
        Me.picBridge.Name = "picBridge"
        Me.picBridge.Size = New System.Drawing.Size(16, 16)
        Me.picBridge.TabIndex = 8
        Me.picBridge.TabStop = False
        '
        'picHeavyBridge
        '
        Me.picHeavyBridge.Image = CType(resources.GetObject("picHeavyBridge.Image"), System.Drawing.Image)
        Me.picHeavyBridge.Location = New System.Drawing.Point(312, 328)
        Me.picHeavyBridge.Name = "picHeavyBridge"
        Me.picHeavyBridge.Size = New System.Drawing.Size(16, 16)
        Me.picHeavyBridge.TabIndex = 9
        Me.picHeavyBridge.TabStop = False
        '
        'tmrGeneral
        '
        Me.tmrGeneral.Interval = 10
        '
        'picBlankImage
        '
        Me.picBlankImage.BackColor = System.Drawing.Color.Silver
        Me.picBlankImage.Image = CType(resources.GetObject("picBlankImage.Image"), System.Drawing.Image)
        Me.picBlankImage.Location = New System.Drawing.Point(248, 136)
        Me.picBlankImage.Name = "picBlankImage"
        Me.picBlankImage.Size = New System.Drawing.Size(31, 31)
        Me.picBlankImage.TabIndex = 10
        Me.picBlankImage.TabStop = False
        Me.picBlankImage.Visible = False
        '
        'FlexMapViewerC
        '
        Me.Controls.Add(Me.pnlBorder)
        Me.Controls.Add(Me.lblZoom)
        Me.Controls.Add(Me.lblCoordinates)
        Me.Controls.Add(Me.txtZoom)
        Me.Controls.Add(Me.txtY)
        Me.Controls.Add(Me.txtX)
        Me.Controls.Add(Me.picHeavyBridge)
        Me.Controls.Add(Me.picBridge)
        Me.Controls.Add(Me.picSmallBridge)
        Me.Controls.Add(Me.picTempBridge)
        Me.Name = "FlexMapViewerC"
        Me.Size = New System.Drawing.Size(464, 384)
        Me.pnlBorder.ResumeLayout(False)
        Me.ResumeLayout(False)

    End Sub

#End Region

    Public Event DisplayClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    Public Event MapScroll()
    Public Event Rendered()
    Public Event UndoRequest()
    Public Event EnterPressed()
    Public Event BackspacePressed()
    Public Event DisplayMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
    Public Event DisplayMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)

    Private c_Module As String = "FlexMapViewerC"
    Private c_DefaultVertexSize As Int16 = 3
    Private c_SelectionColor As Color = Color.Yellow
    Private c_MinimumZoom As Single = 0.1
    Private c_MaximumZoom As Single = 2.0

    ' zoom is going to wait a while I think.
    Private zoom As Single       '0.01 to 2.0: 1% to 200%

    ' property variables
    Private m_ZoomFactor As Single = 1
    Private m_OffsetX As Integer
    Private m_OffsetY As Integer
    Private m_Rendered As Boolean
    Private m_BMP As Bitmap   ' a bmp of our map
    Private m_FMP As New FMPLib01.FlexMapData()
    Private m_Map As Image
    Private m_WaypointColor As System.Drawing.Color = Color.Beige
    Private m_FeaturePathOutlineColor As System.Drawing.Color = Color.Yellow
    Private m_VertexColor As System.Drawing.Color = Color.AntiqueWhite
    Private m_VertexSize As Int16 = c_DefaultVertexSize
    Private m_showPaths As Boolean = False
    Private m_showLabels As Boolean = False
    Private m_ShowScale As Boolean = False
    Private m_ShowGrid As Boolean = False
    Private m_labelColor As Color = Color.Yellow
    Private m_labelSize As Int16 = 16
    Private m_selectedBridge As FMPLib01.FlexMapData.Bridge
    Private m_bridgeSelected As Boolean = False
    Private m_selectionColor As Color = c_SelectionColor
    Private m_GridColorOne As Color = Color.DarkBlue

    Private dx As Single
    Private dy As Single

#Region "picDisplay Events"
    Private Sub picDisplay_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseUp
        Dim zoomPoint As Point
        Dim zoom As Single
        If m_ZoomFactor = 1.0 Then
            zoom = m_ZoomFactor
        Else
            zoom = 0
        End If
        zoomPoint.X = e.X - OffSetX + ((e.X - OffSetX) * zoom)
        zoomPoint.Y = e.Y - OffSetY + ((e.Y - OffSetY) * zoom)
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, zoomPoint.X, zoomPoint.Y, e.Delta)

        RaiseEvent DisplayClick(sender, j)
    End Sub

    Private Sub mouseScrollMap2(ByVal e As MouseEventArgs)
        dx += 1
        dy += 1

        Dim g As Graphics = picDisplay.CreateGraphics
        g.TranslateTransform(dx, dy)
        picDisplay.Invalidate()

    End Sub

    Private Sub picDisplay_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseMove
        MouseScrollMap(e)
    End Sub

    Private Sub MouseScrollMap(ByVal e As System.Windows.Forms.MouseEventArgs)
        Dim zoomPoint As Point
        Dim zoom As Single
        Dim xdiff As Integer
        Dim ydiff As Integer

        Static Last As Point

        If e.Button = MouseButtons.Right Then
            xdiff = (picDisplay.Left + e.X - Last.X) - picDisplay.Left
            ydiff = (picDisplay.Top + e.Y - Last.Y) - picDisplay.Top

            If xdiff < 0 Then
                picDisplay.Left -= Abs(xdiff) / 2
            ElseIf xdiff = 0 Then
                '// nuttin
            Else
                If picDisplay.Left + Abs(xdiff) / 2 > 2 Then xdiff = 2
                picDisplay.Left += Abs(xdiff) / 2
            End If

            If ydiff < 0 Then
                picDisplay.Top -= Abs(ydiff) / 2
            ElseIf ydiff = 0 Then
                '// nuttin
            Else
                If picDisplay.Top + Abs(ydiff) / 2 > 2 Then ydiff = 2
                picDisplay.Top += Abs(ydiff) / 2
            End If

            '// make sure we haven't gotten all silly as far as moving the map around
            CheckExtents()

        End If

        If m_ZoomFactor = 1.0 Then
            zoom = m_ZoomFactor
        Else
            zoom = 0
        End If

        Last.X = e.X
        Last.Y = e.Y

        zoomPoint.X = e.X - OffSetX + ((e.X - OffSetX) * zoom)
        zoomPoint.Y = e.Y - OffSetY + ((e.Y - OffSetY) * zoom)

        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, zoomPoint.X, zoomPoint.Y, e.Delta)

        RaiseEvent DisplayMouseMove(j)
    End Sub

    Private Sub CheckExtents()
        '// checks to see if the map is out of range as far as the extents go.
        Dim x As Integer

        If picDisplay.Left > 2 Then picDisplay.Left = 2
        If picDisplay.Top > 2 Then picDisplay.Top = 2

    End Sub

    Private Sub picDisplay_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseDown
        Dim zoomPoint As Point
        Dim zoom As Single
        If m_ZoomFactor = 1.0 Then
            zoom = m_ZoomFactor
        Else
            zoom = 0
        End If
        zoomPoint.X = e.X - OffSetX + ((e.X - OffSetX) * zoom)
        zoomPoint.Y = e.Y - OffSetY + ((e.Y - OffSetY) * zoom)
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, zoomPoint.X, zoomPoint.Y, e.Delta)

        RaiseEvent DisplayMouseDown(j)
    End Sub
#End Region

#Region "Map Redraw and Position"

    Public Sub ResetPosition()
        ' resets zoom and offsets
        m_OffsetX = 0
        m_OffsetY = 0
        m_ZoomFactor = 1
        RedrawMap()
    End Sub

    Public Sub RedrawMap()
        RenderToDisplay()
        SetPosition()
    End Sub

    Overridable Sub RenderToDisplay()
        If Not m_FMP Is Nothing Then
            If m_Rendered = False Then Exit Sub
            Dim im As Image = New Bitmap(m_FMP.Width, m_FMP.Height)
            Dim g As Graphics = Graphics.FromImage(im)

            m_FMP.Render(g, g.VisibleClipBounds, m_showPaths, , m_ZoomFactor, m_ZoomFactor)

            'add bridges and labels
            DrawBridges(g)
            DrawLabels(g)
            DrawScale(g)
            DrawRoads(g)

            picDisplay.BackgroundImage = Bitmap.FromFile("C:\t.bmp")
            m_BMP = im

            g.Dispose()
            GC.Collect()

            m_Rendered = True
            Debug.WriteLine("Rendered from Viewer C")
            RaiseEvent Rendered()

        End If
    End Sub

    Protected Sub DrawRoads(ByRef g As Graphics)
        Dim aroad As FMPLib01.Road
        Dim sp As New Pen(Color.Brown, 2)
        Dim spborder As New Pen(Color.Black, 4)

        If m_FMP.Roads Is Nothing Then m_FMP.Roads = New FMPLib01.Roads

        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
        For Each aroad In m_FMP.Roads
            If aroad.RoadType = FMPLib01.FlexMapData.RoadType.MajorRoad Then
                sp.Width = 1
                spborder.Width = 5
                sp.Color = Color.Yellow
                spborder.Color = Color.Black
            Else
                sp.Width = 2
                spborder.Width = 4
                sp.Color = Color.Brown
                spborder.Color = Color.Black
            End If
            g.DrawLine(spborder, aroad.StartPoint, aroad.EndPoint)
            g.DrawLine(sp, aroad.StartPoint, aroad.EndPoint)
        Next
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed
        sp.Dispose()
        spborder.Dispose()

    End Sub

    Protected Sub SetPosition()
        ' used for scrolling
        If picDisplay.Image Is Nothing Then
            OffSetX = 0
            OffSetY = 0
            Exit Sub
        End If

        If m_Rendered = False Then Exit Sub

        Dim im As Image = New Bitmap(m_FMP.Width, m_FMP.Height)
        Dim g As Graphics = Graphics.FromImage(im)

        Try
            g.DrawImage(m_BMP, OffSetX, OffSetY)
            picDisplay.Image = im.Clone
            g.Dispose()
            im.Dispose()
            GC.Collect()
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

        RaiseEvent MapScroll()

    End Sub
#End Region

#Region "Supporting Map: Labels, Bridges"
    Overridable Sub DrawLabels(ByVal g As Graphics)
        If ShowLabels = False Then Exit Sub

        Dim lab As FMPLib01.FlexMapData.MapLabel
        Dim fnt As New Font("arial", m_labelSize)
        Dim br As New SolidBrush(m_labelColor)

        Try
            For Each lab In FMPData.Labels
                Dim pth As New GraphicsPath()
                Dim pnt As New PointF(lab.x, lab.y)

                pth.AddString(lab.text, System.Drawing.FontFamily.GenericSerif, System.Drawing.FontStyle.Regular, m_labelSize, pnt, System.Drawing.StringFormat.GenericDefault)

                Dim bounds As RectangleF = pth.GetBounds
                Dim boundsBrush As New SolidBrush(lab.backgroundColor)
                ' increase the size of the box by 1 pixel all the way around
                bounds.X -= 1
                bounds.Y -= 1
                bounds.Width += 3
                bounds.Height += 3

                ' do the markbox. The markbox is a square around the actual position of the label, its basically an arrow.
                Dim markBoxSolid As New RectangleF(bounds.X - 3, bounds.Y - 3, 6, 6)
                Dim markBrush As New SolidBrush(Color.Red)
                Dim markBoxBounds As New Rectangle(markBoxSolid.X, markBoxSolid.Y, markBoxSolid.Width, markBoxSolid.Height)
                g.FillRectangle(markBrush, markBoxSolid)
                g.DrawRectangle(Pens.Black, markBoxBounds)
                markBrush.Dispose()

                Dim boundsBox As New Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height)
                g.FillRectangle(boundsBrush, bounds)
                g.DrawRectangle(Pens.Black, boundsBox)
                boundsBrush.Dispose()

                Dim textBrush As New SolidBrush(lab.foreColor)
                'br.Color = lab.foreColor
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                g.FillPath(textBrush, pth)
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                textBrush.Dispose()

            Next


        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

    Overridable Sub DrawBridges(ByVal g As Graphics)
        Dim bri As FMPLib01.FlexMapData.Bridge

        Try
            For Each bri In FMPData.Bridges
                Dim bmp As Bitmap
                Dim bridgeCoord = New PointF(bri.x, bri.y)

                Select Case bri.type
                    Case FMPLib01.FlexMapData.BridgeType.temporaryBridge
                        bmp = picTempBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.smallBridge
                        bmp = picSmallBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.mediumBridge
                        bmp = picBridge.Image
                    Case FMPLib01.FlexMapData.BridgeType.heavyBridge
                        bmp = picHeavyBridge.Image
                End Select
                bmp.MakeTransparent(Color.FromArgb(255, 0, 255))
                bridgeCoord.x -= bmp.Width / 2
                bridgeCoord.y -= bmp.Height / 2
                ' check for selection first
                If BridgeSelected Then
                    If SelectedBridge.Equals(bri) Then
                        ' draw a yellow splotch where the bridge will go (of course and a little bigger)
                        Dim selBrush As New SolidBrush(m_selectionColor)
                        Dim modLocation As New PointF(bridgeCoord.x - 3, bridgeCoord.y - 3)
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                        g.FillEllipse(selBrush, modLocation.X, modLocation.Y, bmp.Width + 5, bmp.Height + 5)
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                    End If
                End If
                ' draw the bridge
                g.DrawImage(bmp, bridgeCoord.x, bridgeCoord.y)
            Next
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

    Overridable Sub DrawScale(ByRef g As Graphics)
        If m_ShowScale = False Then Exit Sub
        Try
            Dim scaleLineStart As New Point(40, 40)
            Dim scaleLineEnd As New Point(FMPData.MapScale.PixelCount + 40, 40)
            Dim scaleLinePen As New Pen(Color.Yellow, 4)
            Dim rect As New RectangleF(30, 30, (scaleLineEnd.X - 20), 30)

            If rect.Width < 60 Then rect.Width = 60
            Dim rectBrush As New SolidBrush(Color.FromArgb(100, 0, 0, 0))
            Dim miles As Integer = FMPData.MapScale.MilesPerPixelCount
            '            Dim milesText As String

            g.FillRectangle(rectBrush, rect)
            g.DrawRectangle(Pens.Black, New Rectangle(rect.X, rect.Y, rect.Width, rect.Height))
            g.DrawLine(scaleLinePen, scaleLineStart, scaleLineEnd)
            g.DrawString(miles & " " & FMPData.unitName, Me.Font, Brushes.Yellow, 45, 45)

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Public Overridable Sub DrawGrid(ByRef g As Graphics)
        If m_ShowGrid = False Then Exit Sub

        Try
            Dim x As Integer
            Dim y As Integer
            Dim stepCounter As Integer = 0 ' just before the first letter character in the ascii codes
            Dim f As New Font(Me.Font.FontFamily, 12, FontStyle.Bold)
            Dim ch As Char

            Dim fatterpen As New Pen(Color.FromArgb(100, 210, 210, 210), 3)

            For x = 1 To FMPData.Width Step FMPData.MapScale.PixelCount
                ' draw the vertical lines
                g.DrawLine(fatterpen, x, 0, x, FMPData.Height)
                g.DrawLine(Pens.DarkBlue, x, 0, x, FMPData.Height)
                ' draw a grid identifier
                g.DrawString(stepCounter, f, Brushes.DarkBlue, x - (FMPData.MapScale.PixelCount / 2), 10)
                stepCounter += 1
            Next

            stepCounter = 0

            For y = 1 To FMPData.Height Step FMPData.MapScale.PixelCount
                ' draw a line for the grid
                g.DrawLine(fatterpen, 0, y, FMPData.Width, y)
                g.DrawLine(Pens.DarkBlue, 0, y, FMPData.Width, y)
                ' draw grid identifier
                g.DrawString(stepCounter, f, Brushes.DarkBlue, 10, y - (FMPData.MapScale.PixelCount / 2))
                stepCounter += 1
            Next

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

#End Region

#Region "Key Pressing"
    Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        If ActiveControl Is pnlBorder Then
            ' ignore arrows
            Select Case keyData
                Case Keys.Left
                    OffSetX += 10
                    SetPosition()
                    Return True
                Case Keys.Right
                    OffSetX -= 10
                    SetPosition()
                    Return True
                Case Keys.Down
                    OffSetY -= 10
                    SetPosition()
                    Return True
                Case Keys.Up
                    OffSetY += 10
                    SetPosition()
                    Return True
                Case Keys.Add
                    'TODO: Zooming
                    'ZoomFactor += 0.1
                Case Keys.Subtract
                    'ZoomFactor -= 0.1
                Case Keys.Tab
                    ' tabbing out of the panel
                    pnlBorder.BackColor = System.Drawing.Color.Black
                Case Keys.Enter
                    RaiseEvent EnterPressed()
                Case Keys.Back
                    RaiseEvent BackspacePressed()
            End Select

        Else
            ' we are not currently the active control.
            pnlBorder.BackColor = System.Drawing.Color.Black
        End If

        If ActiveControl Is txtZoom Then
            If keyData = Keys.Tab Then
                ' since tab was used to get here, lets change the border color to gold.
                pnlBorder.BackColor = System.Drawing.Color.Gold
                pnlBorder.Select()
                Return True
            End If

        End If

        ' catch shift+tab
        If ActiveControl Is txtX Then
            If (keyData.ToString = "Tab, Shift") Then
                pnlBorder.BackColor = System.Drawing.Color.Gold
                pnlBorder.Select()
                Return True
            End If
        End If

        ' handles anything else
        Return MyBase.ProcessDialogKey(keyData)
    End Function

    Private Sub pnlBorder_Click(ByVal sender As Object, ByVal e As EventArgs) Handles pnlBorder.Click
        pnlBorder.BackColor = System.Drawing.Color.Gold
        pnlBorder.Select()
    End Sub

    Private Sub picDisplay_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles picDisplay.Click
        pnlBorder.BackColor = System.Drawing.Color.Gold
        pnlBorder.Focus()
        pnlBorder.Select()

    End Sub


    Private Sub pnlBorder_Validating(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles pnlBorder.Validating
        pnlBorder.BackColor = System.Drawing.Color.Black
    End Sub
#End Region

#Region "Additional Drawing, FeaturePath, Vertex"
    Friend Sub DrawSimpleLine(ByVal fromPt As PointF, ByVal toPt As PointF, ByVal lineColor As Color, ByVal width As Integer)
        DrawSimpleLine(picDisplay.CreateGraphics, fromPt, toPt, lineColor, width)

    End Sub

    Friend Sub DrawSimpleLine(ByVal g As Graphics, ByVal fromPt As PointF, ByVal toPt As PointF, ByVal lineColor As Color, ByVal width As Integer)
        Try
            Dim penman As New Pen(lineColor, width)
            g.TranslateTransform(OffSetX, OffSetY)
            g.DrawLine(penman, fromPt.X, fromPt.Y, toPt.X, toPt.Y)
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Friend Sub DrawFeaturePath(ByVal gPath As GraphicsPath, ByVal pathCol As Color, ByVal vertexColor As Color, ByVal vertexSize As Int16)
        Dim g As Graphics = picDisplay.CreateGraphics
        DrawFeaturePath(g, gPath, pathCol, vertexColor, vertexSize)
    End Sub

    Friend Sub DrawFeaturePath(ByRef g As Graphics, ByVal gPath As GraphicsPath, ByVal pathCol As Color, ByVal vertexColor As Color, ByVal vertexSize As Int16)
        Try
            Dim pnt As PointF
            Dim penman As New Pen(pathCol)

            g.TranslateTransform(OffSetX, OffSetY)
            g.DrawPath(penman, gPath)
            ' draw vertices
            penman.Color = vertexColor

            For Each pnt In gPath.PathPoints
                DrawVertex(g, pnt, vertexSize, vertexColor)
            Next
            g.Dispose()
        Catch ex As ArgumentException
            Exit Sub
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Public Sub DrawFeaturePath(ByVal gPath As GraphicsPath)
        ' a featurepath is a shape drawn on the map representing a certain type of terrain.
        ' this is the default method, provided to use the property values
        DrawFeaturePath(gPath, m_FeaturePathOutlineColor, m_VertexColor, m_VertexSize)

    End Sub

    Public Sub DrawVertex(ByVal g As Graphics, ByVal pnt As PointF, ByVal vertexSize As Int16, ByVal vertexColor As Color)
        Dim penman As New Pen(vertexColor)
        g.DrawRectangle(penman, CType((pnt.X - vertexSize / 2), Single), CType(pnt.Y - (vertexSize / 2), Single), vertexSize, vertexSize)
    End Sub
#End Region

#Region "Properties"

    Public Property ShowGrid() As Boolean
        Get
            Return m_ShowGrid
        End Get
        Set(ByVal Value As Boolean)
            m_ShowGrid = Value
        End Set
    End Property

    Protected Property ZoomFactor() As Single
        Get
            Return m_ZoomFactor
        End Get
        Set(ByVal Value As Single)
            If Value > c_MaximumZoom Then
                Value = c_MaximumZoom
            End If
            If Value < c_MinimumZoom Then
                Value = c_MinimumZoom
            End If
            m_ZoomFactor = Value
            RedrawMap()
        End Set
    End Property

    Public Property ShowScale() As Boolean
        Get
            Return m_ShowScale
        End Get
        Set(ByVal Value As Boolean)
            m_ShowScale = Value
            RedrawMap()
        End Set
    End Property

    Public Property BridgeSelected() As Boolean
        Get
            Return m_bridgeSelected
        End Get
        Set(ByVal Value As Boolean)
            m_bridgeSelected = Value
        End Set
    End Property

    Public Property SelectedBridge() As FMPLib01.FlexMapData.Bridge
        Get
            ' this is used to pass around the selected bridge, but also to select one from outside (like... from a listbox, no?)
            Return m_selectedBridge
        End Get
        Set(ByVal Value As FMPLib01.FlexMapData.Bridge)
            m_selectedBridge = Value
            If m_selectedBridge Is Nothing Then
                m_bridgeSelected = False
            Else
                m_bridgeSelected = True
            End If
            ' if we provided a selected bridge, we must redraw the map
            'RedrawMap()
        End Set
    End Property

    Public Property LabelSize() As Int16
        Get
            Return m_labelSize
        End Get
        Set(ByVal Value As Int16)
            m_labelSize = Value
        End Set
    End Property

    Public Property LabelColor() As Color
        Get
            Return m_labelColor
        End Get
        Set(ByVal Value As Color)
            m_labelColor = Value
        End Set
    End Property

    Public Property ShowLabels() As Boolean
        Get
            Return m_showLabels
        End Get
        Set(ByVal Value As Boolean)
            m_showLabels = Value
        End Set
    End Property

    Public Property ShowPaths() As Boolean
        Get
            Return m_showPaths
        End Get
        Set(ByVal Value As Boolean)
            m_showPaths = Value
            RedrawMap()
        End Set
    End Property

    Protected ReadOnly Property FMP() As FMPLib01.FlexMapData
        Get
            Return m_FMP
        End Get

    End Property

    Protected Property Rendered_b() As Boolean
        Get
            Return m_Rendered
        End Get
        Set(ByVal Value As Boolean)
            m_Rendered = Value
        End Set
    End Property

    Protected Property BMP() As Bitmap
        Get
            Return m_BMP
        End Get
        Set(ByVal Value As Bitmap)
            m_BMP = Value
        End Set
    End Property

    Friend Property OffSetX() As Integer
        Get
            Return m_OffsetX
        End Get
        Set(ByVal Value As Integer)
            m_OffsetX = Value
            SetMaxScroll()
        End Set
    End Property

    Friend Property OffSetY() As Int16
        Get
            Return m_OffsetY
        End Get
        Set(ByVal Value As Int16)
            m_OffsetY = Value
            SetMaxScroll()
        End Set

    End Property

    Public Property FMPData() As FMPLib01.FlexMapData
        Get
            Return m_FMP
        End Get
        Set(ByVal Value As FMPLib01.FlexMapData)
            If Value Is Nothing Then Exit Property

            m_FMP = Value
            m_BMP = New Bitmap(m_FMP.Width, m_FMP.Height)
            m_Rendered = True
            RenderToDisplay()
        End Set
    End Property

    Public Property FeaturePathOutlineColor() As Color
        Get
            Return m_FeaturePathOutlineColor
        End Get
        Set(ByVal Value As Color)
            m_FeaturePathOutlineColor = Value
        End Set
    End Property

    Public Property VertexColor() As Color
        Get
            Return m_VertexColor
        End Get
        Set(ByVal Value As Color)
            m_VertexColor = Value
        End Set
    End Property

    Public Property VertexSize() As Int16
        Get
            Return m_VertexSize
        End Get
        Set(ByVal Value As Int16)
            m_VertexSize = Value
        End Set
    End Property

    Public ReadOnly Property MapBitmap() As Bitmap
        Get
            Return m_BMP
        End Get
    End Property

#End Region


    Public Sub OpenMap(ByVal filePath As String)
        ' this sets up our beloved map.
        m_FMP = New FMPLib01.FlexMapData()
        m_FMP = m_FMP.OpenMap(filePath)
        m_BMP = New Bitmap(m_FMP.Width, m_FMP.Height)
        ' set the size of the picturebox NOW!!
        picDisplay.Width = m_BMP.Width
        picDisplay.Height = m_BMP.Height
        m_Rendered = True
        RenderToDisplay()

    End Sub

    Private Sub FlexMapViewerC_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        pnlBorder.Select()
    End Sub

    Public Sub DrawScaledMap(ByVal g As Graphics)
        Try
            g.DrawImage(m_BMP, g.VisibleClipBounds)
        Catch ex As Exception

        End Try
    End Sub

    Overridable Sub SetMaxScroll()
        If m_Rendered = False Then
            m_OffsetX = 0
            m_OffsetY = 0
            Exit Sub
        End If

        ' set maximum scrolling
        If m_OffsetX > 0 Then m_OffsetX = 0
        If m_OffsetY > 0 Then m_OffsetY = 0
        If m_OffsetX < -1 * (m_FMP.Width - picDisplay.Width) Then m_OffsetX = -1 * (m_FMP.Width - picDisplay.Width)
        If m_OffsetY < -1 * (m_FMP.Height - picDisplay.Height) Then m_OffsetY = -1 * (m_FMP.Height - picDisplay.Height)

        ' catch for display being larger than map height and width
        If picDisplay.Width > m_FMP.Width Then m_OffsetX = 0
        If picDisplay.Height > m_FMP.Height Then m_OffsetY = 0
    End Sub

    Private Sub pnlBorder_Layout(ByVal sender As Object, ByVal e As System.Windows.Forms.LayoutEventArgs) Handles pnlBorder.Layout
        pnlBorder.BackColor = Color.Black
    End Sub

End Class
